package config

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/spf13/viper"
)

// Config holds all configuration for the application
type Config struct {
	// Application settings
	App AppConfig `mapstructure:"app"`

	// Kafka settings
	Kafka KafkaConfig `mapstructure:"kafka"`

	// MySQL settings
	MySQL MySQLConfig `mapstructure:"mysql"`

	// Kubernetes settings
	Kubernetes KubernetesConfig `mapstructure:"kubernetes"`
}

// AppConfig holds application-specific configuration
type AppConfig struct {
	LogLevel    string `mapstructure:"log_level" validate:"required,oneof=debug info warn error"`
	MetricsPort int    `mapstructure:"metrics_port" validate:"required,min=1,max=65535"`
	Environment string `mapstructure:"environment" validate:"required,oneof=development staging production"`
}

// KafkaConfig holds Kafka-specific configuration
type KafkaConfig struct {
	Brokers       []string `mapstructure:"brokers" validate:"required,min=1"`
	Topic         string   `mapstructure:"topic" validate:"required"`
	ConsumerGroup string   `mapstructure:"consumer_group" validate:"required"`
	StatusTopic   string   `mapstructure:"status_topic" validate:"required"`
}

// MySQLConfig holds MySQL-specific configuration
type MySQLConfig struct {
	Host     string `mapstructure:"host" validate:"required"`
	Port     int    `mapstructure:"port" validate:"required,min=1,max=65535"`
	Database string `mapstructure:"database" validate:"required"`
	Username string `mapstructure:"username" validate:"required"`
	Password string `mapstructure:"password" validate:"required"`
	SSLMode  string `mapstructure:"ssl_mode" validate:"required,oneof=disable require verify-ca verify-full"`

	// Connection pool settings
	MaxOpenConns    int           `mapstructure:"max_open_conns" validate:"required,min=1"`
	MaxIdleConns    int           `mapstructure:"max_idle_conns" validate:"required,min=0"`
	ConnMaxLifetime time.Duration `mapstructure:"conn_max_lifetime" validate:"required"`
}

// KubernetesConfig holds Kubernetes-specific configuration
type KubernetesConfig struct {
	Kubeconfig string `mapstructure:"kubeconfig"`
	Namespace  string `mapstructure:"namespace" validate:"required"`
	Context    string `mapstructure:"context"`
}

// LoadConfig loads configuration from file and environment variables
func LoadConfig(configPath string) (*Config, error) {
	viper.SetConfigName("config")
	viper.SetConfigType("yaml")

	if configPath != "" {
		viper.SetConfigFile(configPath)
	} else {
		viper.AddConfigPath(".")
		viper.AddConfigPath("./configs")
		viper.AddConfigPath("/etc/cloud-controller")
	}

	// Set defaults
	setDefaults()

	// Read environment variables
	viper.AutomaticEnv()
	viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))

	// Read config file
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
			return nil, fmt.Errorf("failed to read config file: %w", err)
		}
		// Config file not found, but that's okay if we have env vars
	}

	var config Config
	if err := viper.Unmarshal(&config); err != nil {
		return nil, fmt.Errorf("failed to unmarshal config: %w", err)
	}

	// Validate configuration
	if err := validateConfig(&config); err != nil {
		return nil, fmt.Errorf("config validation failed: %w", err)
	}

	return &config, nil
}

// setDefaults sets default values for configuration
func setDefaults() {
	// App defaults
	viper.SetDefault("app.log_level", "info")
	viper.SetDefault("app.metrics_port", 8080)
	viper.SetDefault("app.environment", "development")

	// Kafka defaults
	viper.SetDefault("kafka.brokers", []string{"localhost:9092"})
	viper.SetDefault("kafka.topic", "jobs")
	viper.SetDefault("kafka.consumer_group", "cloud-controller")
	viper.SetDefault("kafka.status_topic", "job-status")

	// MySQL defaults
	viper.SetDefault("mysql.host", "localhost")
	viper.SetDefault("mysql.port", 3306)
	viper.SetDefault("mysql.database", "cloud_controller")
	viper.SetDefault("mysql.ssl_mode", "disable")
	viper.SetDefault("mysql.max_open_conns", 25)
	viper.SetDefault("mysql.max_idle_conns", 5)
	viper.SetDefault("mysql.conn_max_lifetime", "5m")

	// Kubernetes defaults
	viper.SetDefault("kubernetes.namespace", "default")
}

// validateConfig validates the configuration
func validateConfig(config *Config) error {
	// Basic validation is handled by struct tags
	// Additional custom validation can be added here

	// Check if required environment variables are set
	if config.MySQL.Username == "" {
		config.MySQL.Username = os.Getenv("MYSQL_USERNAME")
	}
	if config.MySQL.Password == "" {
		config.MySQL.Password = os.Getenv("MYSQL_PASSWORD")
	}

	if config.MySQL.Username == "" || config.MySQL.Password == "" {
		return fmt.Errorf("MySQL username and password are required")
	}

	return nil
}

// GetDSN returns the MySQL DSN string
func (c *MySQLConfig) GetDSN() string {
	return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&ssl-mode=%s",
		c.Username, c.Password, c.Host, c.Port, c.Database, c.SSLMode)
}

// GetKafkaBrokers returns Kafka brokers as a slice
func (c *KafkaConfig) GetKafkaBrokers() []string {
	return c.Brokers
}

// GetStatusTopic returns the status topic name
func (c *KafkaConfig) GetStatusTopic() string {
	if c.StatusTopic == "" {
		return c.Topic + "-status"
	}
	return c.StatusTopic
}
